﻿using System;
using System.Collections.Generic;
using System.Text;
using NUnit.Framework;
using Rhino.Mocks;
using TSVNAddin.SVN;
using EnvDTE;
using EnvDTE80;

namespace TSVNAddin.Core.Test
{
	[TestFixture]
	public class RepositoryFixture
	{
		[Test]
		public void ShouldFoundRootPath()
		{
			string fileName = @"c:\svnroot\myproject\trunk\file.txt";

			var svnClientAdapter = MockRepository.GenerateMock<SVNClientAdapter>();
			svnClientAdapter.Expect(x => x.GetRepositoryInfo(fileName)).Return(
				new SVNInfoArgs() {
					RootAddress = new Uri(@"http://localhost/svnroot/"),
					FileAddress = new Uri(@"http://localhost/svnroot/myproject/trunk/file.txt")
				}
			);

			var solution = MockRepository.GenerateMock<SolutionAdapter>((DTE2)null);
			solution.Stub(x => x.GetFileName()).Return(fileName);

			Repository repository = new Repository(solution, svnClientAdapter);
			string retRepositoryPath = repository.GetWorkingRoot();

			Assert.AreEqual(@"c:\svnroot\", retRepositoryPath);
			svnClientAdapter.VerifyAllExpectations();
		}

		[Test]
		public void ShouldReturnStringEmptyOnFindRootPathWhenGetRepositoryPathReturnNULL()
		{
			string fileName = @"c:\svnroot\myproject\trunk\file.txt";

			var svnClientAdapter = MockRepository.GenerateMock<SVNClientAdapter>();
			svnClientAdapter.Expect(x => x.GetRepositoryInfo(fileName)).Return(null);

			var solution = MockRepository.GenerateMock<SolutionAdapter>((DTE2)null);
			solution.Stub(x => x.GetFileName()).Return(fileName);

			Repository repository = new Repository(solution, svnClientAdapter);
			string retRepositoryPath = repository.GetWorkingRoot();

			Assert.AreEqual(string.Empty, retRepositoryPath);
			svnClientAdapter.VerifyAllExpectations();
		}

		[Test]
		public void ShouldReturnLastRootIfFileNameNoChanged()
		{
			var svnClientAdapter = MockRepository.GenerateMock<SVNClientAdapter>();
			svnClientAdapter.Expect(x => x.GetRepositoryInfo(@"c:\svnroot\test.sln")).Return(
				new SVNInfoArgs()
				{
					RootAddress = new Uri(@"http://localhost/svnroot/"),
					FileAddress = new Uri(@"http://localhost/svnroot/test.sln")
				}
			).Repeat.Once();

			var solution = MockRepository.GenerateMock<SolutionAdapter>((DTE2)null);
			solution.Stub(x => x.GetFileName()).Return(@"c:\svnroot\test.sln");

			Repository repository = new Repository(solution, svnClientAdapter);

			string rootPath1 = repository.GetWorkingRoot();
			string rootPath2 = repository.GetWorkingRoot();

			Assert.AreEqual(@"c:\svnroot\", rootPath1);
			Assert.AreEqual(@"c:\svnroot\", rootPath2);

			svnClientAdapter.VerifyAllExpectations();
		}

		[Test]
		public void ShouldReturnStringEmptyIfNewFileNameHasNoRoot()
		{
			var svnClientAdapter = MockRepository.GenerateStrictMock<SVNClientAdapter>();
			svnClientAdapter.Expect(x => x.GetRepositoryInfo(@"c:\svnroot\test.sln")).Return(
				new SVNInfoArgs()
				{
					RootAddress = new Uri(@"http://localhost/svnroot/"),
					FileAddress = new Uri(@"http://localhost/svnroot/test.sln")
				}
			);

			svnClientAdapter.Expect(x => x.GetRepositoryInfo(@"c:\svnroot2\test2.sln")).Return(null);

			var solution = MockRepository.GenerateMock<SolutionAdapter>((DTE2)null);
			solution.Stub(x => x.GetFileName()).Return(@"c:\svnroot\test.sln").Repeat.Once();
			solution.Stub(x => x.GetFileName()).Return(@"c:\svnroot2\test2.sln");
			
			Repository repository = new Repository(solution, svnClientAdapter);

			string rootPath1 = repository.GetWorkingRoot();
			string rootPath2 = repository.GetWorkingRoot();
			string rootPath3 = repository.GetWorkingRoot();

			Assert.AreEqual(@"c:\svnroot\", rootPath1);
			Assert.AreEqual(string.Empty, rootPath2);
			Assert.AreEqual(string.Empty, rootPath3);

			svnClientAdapter.VerifyAllExpectations();
		}

		[Test]
		public void ShouldActiveWhenSolutionIsOpenedAndRootPathIsNotEmpty()
		{
			string fileName = @"c:\svn\myproject\trunk\file.txt";

			var svnClientAdapter = MockRepository.GenerateMock<SVNClientAdapter>();
			svnClientAdapter.Stub(x => x.GetRepositoryInfo(fileName)).Return(
				new SVNInfoArgs()
				{
					RootAddress = new Uri(@"http://localhost/svnroot/"),
					FileAddress = new Uri(@"http://localhost/svnroot/myproject/trunk/file.txt")
				}
			);

			var solution = MockRepository.GenerateMock<SolutionAdapter>((DTE2)null);
			solution.Stub(x => x.GetFileName()).Return(fileName);
			solution.Stub(x => x.IsOpen()).Return(true);

			Repository repository = new Repository(solution, svnClientAdapter);
			bool isActive = repository.IsActive();

			Assert.IsTrue(isActive);
		}

		[Test]
		public void ShouldNotActiveWhenSolutionIsClosed()
		{
			var solution = MockRepository.GenerateMock<SolutionAdapter>((DTE2)null);
			solution.Stub(x => x.IsOpen()).Return(false);

			Repository repository = new Repository(solution, null);
			bool isActive = repository.IsActive();

			Assert.IsFalse(isActive);
		}

		[Test]
		public void ShouldNotActiveWhenNotExistsSVNInfo()
		{
			string fileName = @"c:\svn\myproject\trunk\file.txt";

			var svnClientAdapter = MockRepository.GenerateMock<SVNClientAdapter>();
			svnClientAdapter.Stub(x => x.GetRepositoryInfo(fileName)).Return(null);

			var solution = MockRepository.GenerateMock<SolutionAdapter>((DTE2)null);
			solution.Stub(x => x.GetFileName()).Return(fileName);
			solution.Stub(x => x.IsOpen()).Return(true);

			Repository repository = new Repository(solution, svnClientAdapter);
			bool isActive = repository.IsActive();

			Assert.IsFalse(isActive);
		}

		[Test]
		public void ShouldReturnFalseOnContainsFileWhenRepositoryIsNotActive()
		{
			var solution = MockRepository.GenerateMock<SolutionAdapter>((DTE2)null);
			solution.Stub(x => x.IsOpen()).Return(false);

			Repository repository = new Repository(solution, null);
			bool contains = repository.Contains(@"c:\svn\myproject\trunk\file.txt");

			Assert.IsFalse(contains);
		}

		[Test]
		public void ShouldReturnFalseOnContainsFileWhenPathDoesntMatch()
		{
			var svnClientAdapter = MockRepository.GenerateStrictMock<SVNClientAdapter>();
			svnClientAdapter.Expect(x => x.GetRepositoryInfo(@"c:\svnroot\test.sln")).Return(
				new SVNInfoArgs()
				{
					RootAddress = new Uri(@"http://localhost/svnroot/"),
					FileAddress = new Uri(@"http://localhost/svnroot/test.sln")
				}
			);

			var solution = MockRepository.GenerateMock<SolutionAdapter>((DTE2)null);
			solution.Stub(x => x.GetFileName()).Return(@"c:\svnroot\test.sln");
			solution.Stub(x => x.IsOpen()).Return(true);

			Repository repository = new Repository(solution, svnClientAdapter);
			bool contains = repository.Contains(@"c:\svnroot2\trunk\file.txt");

			Assert.IsFalse(contains);
		}

		[Test]
		public void ShouldReturnTrueOnContainsFileWhenPathMatch()
		{
			var svnClientAdapter = MockRepository.GenerateStrictMock<SVNClientAdapter>();
			svnClientAdapter.Expect(x => x.GetRepositoryInfo(@"c:\svnroot\test.sln")).Return(
				new SVNInfoArgs()
				{
					RootAddress = new Uri(@"http://localhost/svnroot/"),
					FileAddress = new Uri(@"http://localhost/svnroot/test.sln")
				}
			);

			var solution = MockRepository.GenerateMock<SolutionAdapter>((DTE2)null);
			solution.Stub(x => x.GetFileName()).Return(@"c:\svnroot\test.sln");
			solution.Stub(x => x.IsOpen()).Return(true);

			Repository repository = new Repository(solution, svnClientAdapter);
			bool contains = repository.Contains(@"c:\SvnRoot\Trunk\file.txt");

			Assert.IsTrue(contains);
		}
	}
}
